package cn.ocars.playgame.pencilstudy.ui.components

import android.graphics.Path
import android.graphics.PathMeasure
import cn.ocars.playgame.pencilstudy.ui.components.RecognitionResult
import kotlin.math.*



/**
 * 书写评分组件
 * 支持基于重合度计算和文字识别的双重评分策略
 */
class WritingScoreEvaluator {
    
    companion object {
        private const val SAMPLE_DISTANCE = 3f // 采样距离
        private const val GRID_SIZE = 32 // 高精度网格大小
        private const val OVERLAP_THRESHOLD = 0.1f // 重合判定阈值
    }
    
    /**
     * 评分结果数据类
     */
    data class ScoreResult(
        val totalScore: Float,
        val overlapScore: Float,
        val completenessScore: Float,
        val recognitionScore: Float = 0f,
        val qualityScore: Float = 0f,
        val recognitionResult: RecognitionResult? = null,
        val feedback: String
    )
    
    /**
     * 评估用户书写（智能评分策略）
     */
    fun evaluateWriting(
        userStrokes: List<StrokeData>,
        referenceCharacter: WritingCharacterData
    ): ScoreResult {
        
        val characterType = determineCharacterType(referenceCharacter)
        
        return when (characterType) {
            CharacterType.DIGIT, CharacterType.LETTER, CharacterType.CHINESE -> {
                // 使用文字识别评分
                evaluateWithRecognition(userStrokes, referenceCharacter, characterType)
            }
            CharacterType.STROKE, CharacterType.RADICAL -> {
                // 使用位置偏差评分
                evaluateWithPositionBias(userStrokes, referenceCharacter)
            }
        }
    }
    
    /**
     * 基于文字识别的评分（用于数字、字母、汉字）
     */
    private fun evaluateWithRecognition(
        userStrokes: List<StrokeData>,
        referenceCharacter: WritingCharacterData,
        characterType: CharacterType
    ): ScoreResult {
        
        // 1. 进行文字识别
        println("文字识别调试: 开始识别用户笔迹")
        println("文字识别调试: 用户笔画数=${userStrokes.size}, 目标字符=${referenceCharacter.character}")
        
        val recognitionResult = recognizeCharacter(userStrokes, characterType)
        
        println("文字识别调试: 识别结果=${recognitionResult.recognizedText}, 置信度=${recognitionResult.confidence}")
        
        // 2. 计算识别准确度评分
        val recognitionScore = calculateRecognitionScore(
            recognitionResult, 
            referenceCharacter.character
        )
        
        println("文字识别调试: 识别准确度评分=${recognitionScore}")
        
        // 3. 计算书写质量评分
        val qualityScore = calculateWritingQuality(userStrokes)
        
        // 4. 计算总分（识别准确度80% + 书写质量20%）
        val baseScore = recognitionScore * 0.8f + qualityScore * 0.2f
        
        // 如果识别完全失败，总分不应超过30分
        val totalScore = if (recognitionResult.recognizedText.isEmpty()) {
            (baseScore * 100f).coerceAtMost(30f)
        } else if (recognitionResult.recognizedText != referenceCharacter.character) {
            // 如果识别错误，总分不应超过50分
            (baseScore * 100f).coerceAtMost(50f)
        } else {
            baseScore * 100f
        }
        
        println("文字识别调试: 基础分数=$baseScore, 最终总分=$totalScore")
        
        // 5. 生成反馈
        val feedback = generateRecognitionFeedback(
            recognitionResult, 
            referenceCharacter.character, 
            recognitionScore, 
            qualityScore, 
            totalScore
        )
        
        return ScoreResult(
            totalScore = totalScore.coerceIn(0f, 100f),
            overlapScore = 0f,
            completenessScore = 0f,
            recognitionScore = recognitionScore * 100f,
            qualityScore = qualityScore * 100f,
            recognitionResult = recognitionResult,
            feedback = feedback
        )
    }
    
    /**
     * 基于位置偏差的评分（用于笔画、偏旁）
     */
    private fun evaluateWithPositionBias(
        userStrokes: List<StrokeData>,
        referenceCharacter: WritingCharacterData
    ): ScoreResult {
        
        // 1. 将用户笔迹和参考字符转换为高精度网格
        val userGrid = convertStrokesToGrid(userStrokes)
        val referenceGrid = convertReferenceToGrid(referenceCharacter)
        
        // 2. 计算重合度评分
        val overlapScore = calculateOverlapScore(userGrid, referenceGrid)
        
        // 3. 计算完整度评分
        val completenessScore = calculateCompletenessScore(userGrid, referenceGrid)
        
        // 4. 计算总分（重合度70% + 完整度30%）
        val totalScore = (overlapScore * 0.7f + completenessScore * 0.3f) * 100f
        
        // 5. 生成反馈
        val feedback = generatePositionFeedback(overlapScore, completenessScore, totalScore)
        
        return ScoreResult(
            totalScore = totalScore.coerceIn(0f, 100f),
            overlapScore = overlapScore * 100f,
            completenessScore = completenessScore * 100f,
            feedback = feedback
        )
    }
    
    /**
     * 将用户笔迹转换为高精度网格
     */
    private fun convertStrokesToGrid(userStrokes: List<StrokeData>): Array<FloatArray> {
        val grid = Array(GRID_SIZE) { FloatArray(GRID_SIZE) }
        
        println("用户笔迹转换: 共${userStrokes.size}笔")
        
        for ((strokeIndex, stroke) in userStrokes.withIndex()) {
            val vertices = stroke.vertices
            val widths = stroke.widths
            
            println("第${strokeIndex + 1}笔: ${vertices.size / 3}个点")
            
            // 将OpenGL坐标转换为网格坐标
            for (i in vertices.indices step 3) {
                val glX = vertices[i]
                val glY = vertices[i + 1]
                
                // 转换为归一化坐标(0-1)，修复坐标转换
                val normalizedX = (1 - glX) / 2  // X轴翻转
                val normalizedY = (1 - glY) / 2  // Y轴也需要翻转
                
                // 转换为网格坐标
                val gridX = (normalizedX * (GRID_SIZE - 1)).toInt().coerceIn(0, GRID_SIZE - 1)
                val gridY = (normalizedY * (GRID_SIZE - 1)).toInt().coerceIn(0, GRID_SIZE - 1)
                
                // 调试前几个点的坐标转换
                if (i < 9 && strokeIndex == 0) {
                    println("用户点${i/3}: OpenGL($glX, $glY) -> 归一化($normalizedX, $normalizedY) -> 网格($gridX, $gridY)")
                }
                
                // 获取线宽并转换为网格单位
                val width = if (i / 3 < widths.size) widths[i / 3] else 4.0f
                val gridWidth = (width / 10.0f * 3).coerceIn(1f, 6f) // 增大线宽影响范围
                
                // 在网格中标记笔迹，使用高斯分布模拟笔触
                markStrokeOnGrid(grid, gridX, gridY, gridWidth)
            }
        }
        
        return grid
    }
    
    /**
     * 将参考字符转换为高精度网格
     */
    private fun convertReferenceToGrid(referenceCharacter: WritingCharacterData): Array<FloatArray> {
        val grid = Array(GRID_SIZE) { FloatArray(GRID_SIZE) }
        
        println("参考字符转换: ${referenceCharacter.character}, 共${referenceCharacter.strokes.size}笔")
        
        for ((strokeIndex, strokeInfo) in referenceCharacter.strokes.withIndex()) {
            val path = strokeInfo.path
            val pathMeasure = PathMeasure(path, false)
            val length = pathMeasure.length
            
            println("参考第${strokeIndex + 1}笔: 长度=$length")
            
            if (length > 0) {
                val points = FloatArray(2)
                var distance = 0f
                var pointCount = 0
                
                while (distance <= length) {
                    pathMeasure.getPosTan(distance, points, null)
                    
                    // 参考字符坐标已经是归一化的(0-1)，直接转换为网格坐标
                    val gridX = (points[0] * (GRID_SIZE - 1)).toInt().coerceIn(0, GRID_SIZE - 1)
                    val gridY = ((1.0f - points[1]) * (GRID_SIZE - 1)).toInt().coerceIn(0, GRID_SIZE - 1) // Y轴翻转保持一致
                    
                    // 调试前几个点的坐标转换
                    if (pointCount < 3 && strokeIndex == 0) {
                        println("参考点$pointCount: 归一化(${points[0]}, ${points[1]}) -> 网格($gridX, $gridY)")
                    }
                    
                    // 标准笔触宽度，与用户笔迹匹配
                    val standardWidth = 3.0f
                    markStrokeOnGrid(grid, gridX, gridY, standardWidth)
                    
                    distance += SAMPLE_DISTANCE
                    pointCount++
                }
            }
        }
        
        return grid
    }
    
    /**
     * 在网格上标记笔触（使用高斯分布）
     */
    private fun markStrokeOnGrid(grid: Array<FloatArray>, centerX: Int, centerY: Int, width: Float) {
        val radius = (width).toInt().coerceAtLeast(2) // 增大半径
        
        for (dy in -radius..radius) {
            for (dx in -radius..radius) {
                val x = centerX + dx
                val y = centerY + dy
                
                if (x in 0 until GRID_SIZE && y in 0 until GRID_SIZE) {
                    val distance = sqrt((dx * dx + dy * dy).toFloat())
                    val intensity = if (distance <= width) {
                        exp(-distance * distance / (width * width / 2)) // 调整衰减速度
                    } else {
                        0f
                    }
                    
                    // 累加强度，模拟笔迹重叠
                    grid[y][x] = minOf(1.0f, grid[y][x] + intensity * 0.8f) // 降低强度避免过饱和
                }
            }
        }
    }
    
    /**
     * 计算重合度评分（改进版本）
     */
    private fun calculateOverlapScore(userGrid: Array<FloatArray>, referenceGrid: Array<FloatArray>): Float {
        var overlapSum = 0f
        var referenceSum = 0f
        var userSum = 0f
        var nearOverlapSum = 0f // 近似重合
        
        for (y in 0 until GRID_SIZE) {
            for (x in 0 until GRID_SIZE) {
                val userValue = userGrid[y][x]
                val refValue = referenceGrid[y][x]
                
                // 计算精确重合部分
                overlapSum += minOf(userValue, refValue)
                
                // 计算近似重合（考虑邻近区域）
                if (refValue > OVERLAP_THRESHOLD) {
                    var maxNearbyUser = userValue
                    // 检查3x3邻域
                    for (dy in -1..1) {
                        for (dx in -1..1) {
                            val nx = x + dx
                            val ny = y + dy
                            if (nx in 0 until GRID_SIZE && ny in 0 until GRID_SIZE) {
                                maxNearbyUser = maxOf(maxNearbyUser, userGrid[ny][nx])
                            }
                        }
                    }
                    nearOverlapSum += minOf(maxNearbyUser, refValue) * 0.8f // 近似重合权重
                }
                
                // 计算总的参考面积和用户面积
                referenceSum += refValue
                userSum += userValue
            }
        }
        
        // 综合重合度 = (精确重合 + 近似重合) / 参考面积
        val totalOverlap = overlapSum + (nearOverlapSum - overlapSum) * 0.5f
        return if (referenceSum > 0) {
            (totalOverlap / referenceSum).coerceAtMost(1.0f)
        } else {
            0f
        }
    }
    
    /**
     * 计算完整度评分（改进版本）
     */
    private fun calculateCompletenessScore(userGrid: Array<FloatArray>, referenceGrid: Array<FloatArray>): Float {
        var coveredSum = 0f
        var referenceSum = 0f
        var nearbyCoveredSum = 0f
        
        for (y in 0 until GRID_SIZE) {
            for (x in 0 until GRID_SIZE) {
                val userValue = userGrid[y][x]
                val refValue = referenceGrid[y][x]
                
                referenceSum += refValue
                
                // 如果参考位置有笔迹，检查用户是否覆盖
                if (refValue > OVERLAP_THRESHOLD) {
                    if (userValue > OVERLAP_THRESHOLD) {
                        coveredSum += refValue
                    } else {
                        // 检查邻近区域是否有用户笔迹
                        var hasNearbyUser = false
                        for (dy in -2..2) {
                            for (dx in -2..2) {
                                val nx = x + dx
                                val ny = y + dy
                                if (nx in 0 until GRID_SIZE && ny in 0 until GRID_SIZE) {
                                    if (userGrid[ny][nx] > OVERLAP_THRESHOLD) {
                                        hasNearbyUser = true
                                        break
                                    }
                                }
                            }
                            if (hasNearbyUser) break
                        }
                        if (hasNearbyUser) {
                            nearbyCoveredSum += refValue * 0.6f // 近似覆盖权重
                        }
                    }
                }
            }
        }
        
        // 完整度 = (精确覆盖 + 近似覆盖) / 总参考面积
        val totalCovered = coveredSum + nearbyCoveredSum
        return if (referenceSum > 0) {
            (totalCovered / referenceSum).coerceAtMost(1.0f)
        } else {
            0f
        }
    }
    
    /**
     * 判断字符类型
     */
    private fun determineCharacterType(referenceCharacter: WritingCharacterData): CharacterType {
        // 优先使用字符数据中的类型信息
        if (referenceCharacter.characterType != null) {
            return referenceCharacter.characterType
        }
        
        // 回退到基于字符串的判断
        val character = referenceCharacter.character
        return when {
            character.matches(Regex("[0-9]")) -> CharacterType.DIGIT
            character.matches(Regex("[A-Za-z]")) -> CharacterType.LETTER
            character.matches(Regex("[\\u4e00-\\u9fff]")) -> CharacterType.CHINESE
            character in listOf("横", "竖", "撇", "捺", "点", "钩", "折") -> CharacterType.STROKE
            character.length == 1 && character.matches(Regex("[\\u2e80-\\u2eff\\u2f00-\\u2fdf\\u31c0-\\u31ef]")) -> CharacterType.RADICAL
            else -> CharacterType.CHINESE // 默认为汉字
        }
    }
    
    /**
     * 文字识别主函数
     */
    private fun recognizeCharacter(userStrokes: List<StrokeData>, characterType: CharacterType): RecognitionResult {
        return when (characterType) {
            CharacterType.DIGIT -> recognizeDigit(userStrokes)
            CharacterType.LETTER -> recognizeLetter(userStrokes)
            CharacterType.CHINESE -> recognizeChinese(userStrokes)
            else -> RecognitionResult("", 0f, emptyMap())
        }
    }
    
    /**
     * 数字识别（改进版本，更严格的识别条件）
     */
    private fun recognizeDigit(userStrokes: List<StrokeData>): RecognitionResult {
        println("数字识别调试: 开始识别数字，用户笔画数=${userStrokes.size}")
        
        val features = extractGeometricFeatures(userStrokes)
        val strokeCount = userStrokes.size
        
        println("数字识别调试: 笔画数=$strokeCount")
        
        val candidates = mutableMapOf<String, Float>()
        
        when (strokeCount) {
            1 -> {
                val aspectRatio = features["aspectRatio"] ?: 1f
                val hasVertical = features["hasVerticalLine"] ?: 0f
                val hasHorizontal = features["hasHorizontalLine"] ?: 0f
                val circularity = features["circularity"] ?: 0f
                
                println("数字识别调试: 单笔 - aspectRatio=$aspectRatio, hasVertical=$hasVertical, hasHorizontal=$hasHorizontal")
                
                // 更严格的"1"识别：高宽高比、明显的竖线、很少的横线
                if (aspectRatio > 3.0f && hasVertical > 0.8f && hasHorizontal < 0.2f) {
                    candidates["1"] = 0.9f
                    println("数字识别调试: 符合'1'条件")
                } else if (circularity > 0.8f && aspectRatio > 0.8f && aspectRatio < 1.3f) {
                    // 圆形的"0"
                    candidates["0"] = 0.8f
                    println("数字识别调试: 符合'0'条件")
                }
            }
            2 -> {
                val hasHorizontal = features["hasHorizontalLine"] ?: 0f
                val hasVertical = features["hasVerticalLine"] ?: 0f
                val aspectRatio = features["aspectRatio"] ?: 1f
                
                println("数字识别调试: 双笔 - hasHorizontal=$hasHorizontal, hasVertical=$hasVertical, aspectRatio=$aspectRatio")
                
                // "4"字需要明显的横线和竖线
                if (hasHorizontal > 0.7f && hasVertical > 0.7f && aspectRatio > 0.7f && aspectRatio < 1.5f) {
                    candidates["4"] = 0.8f
                    println("数字识别调试: 符合'4'条件")
                }
            }
            3 -> {
                val circularity = features["circularity"] ?: 0f
                val aspectRatio = features["aspectRatio"] ?: 1f
                
                println("数字识别调试: 三笔 - circularity=$circularity, aspectRatio=$aspectRatio")
                
                // 更严格的圆形数字识别
                if (circularity > 0.8f && aspectRatio > 0.8f && aspectRatio < 1.3f) {
                    candidates["0"] = 0.8f
                    candidates["8"] = 0.7f
                    println("数字识别调试: 符合圆形数字条件")
                }
            }
        }
        
        println("数字识别调试: 候选结果: $candidates")
        
        // 提高识别阈值，如果最高置信度低于0.7，则认为识别失败
        val bestMatch = candidates.maxByOrNull { it.value }
        val result = if (bestMatch != null && bestMatch.value >= 0.7f) {
            RecognitionResult(bestMatch.key, bestMatch.value, features)
        } else {
            RecognitionResult("", 0f, features)
        }
        
        println("数字识别调试: 最终识别结果=${result.recognizedText}, 置信度=${result.confidence}")
        
        return result
    }
    
    /**
     * 字母识别
     */
    private fun recognizeLetter(userStrokes: List<StrokeData>): RecognitionResult {
        val features = extractGeometricFeatures(userStrokes)
        val strokeCount = userStrokes.size
        
        val candidates = mutableMapOf<String, Float>()
        
        when (strokeCount) {
            1 -> {
                val circularity = features["circularity"] ?: 0f
                val aspectRatio = features["aspectRatio"] ?: 1f
                
                if (circularity > 0.8f) {
                    candidates["O"] = 0.9f
                } else if (aspectRatio > 2.0f) {
                    candidates["I"] = 0.8f
                } else {
                    candidates["C"] = 0.6f
                }
            }
            2 -> {
                val hasVertical = features["hasVerticalLine"] ?: 0f
                if (hasVertical > 0.5f) {
                    candidates["H"] = 0.7f
                    candidates["T"] = 0.6f
                }
            }
            3 -> {
                candidates["A"] = 0.7f
                candidates["E"] = 0.6f
            }
        }
        
        val bestMatch = candidates.maxByOrNull { it.value }
        return if (bestMatch != null) {
            RecognitionResult(bestMatch.key, bestMatch.value, features)
        } else {
            RecognitionResult("", 0f, features)
        }
    }
    
    /**
     * 汉字识别（改进版本，更严格的识别条件）
     */
    private fun recognizeChinese(userStrokes: List<StrokeData>): RecognitionResult {
        println("汉字识别调试: 开始识别汉字，用户笔画数=${userStrokes.size}")
        
        val features = extractGeometricFeatures(userStrokes)
        val strokeCount = userStrokes.size
        
        println("汉字识别调试: 笔画数=$strokeCount")
        
        val candidates = mutableMapOf<String, Float>()
        
        when (strokeCount) {
            1 -> {
                val aspectRatio = features["aspectRatio"] ?: 1f
                val angle = features["dominantAngle"] ?: 0f
                val hasHorizontal = features["hasHorizontalLine"] ?: 0f
                
                println("汉字识别调试: 单笔 - aspectRatio=$aspectRatio, angle=$angle, hasHorizontal=$hasHorizontal")
                
                // 更严格的"一"字识别
                if (aspectRatio > 3.0f && abs(angle) < 15f && hasHorizontal > 0.8f) {
                    candidates["一"] = 0.9f
                    println("汉字识别调试: 符合'一'字条件")
                } else if (aspectRatio > 2.0f && abs(angle) > 45f && hasHorizontal < 0.3f) {
                    candidates["丿"] = 0.7f // 撇
                    println("汉字识别调试: 符合'撇'条件")
                }
            }
            2 -> {
                val symmetry = features["symmetry"] ?: 0f
                val convergence = features["convergencePoint"] ?: 0f
                val aspectRatio = features["aspectRatio"] ?: 1f
                
                println("汉字识别调试: 双笔 - symmetry=$symmetry, convergence=$convergence, aspectRatio=$aspectRatio")
                
                // 更严格的"人"字识别：需要高对称性、高收敛性、合适的宽高比
                if (symmetry > 0.7f && convergence > 0.8f && aspectRatio > 0.8f && aspectRatio < 1.5f) {
                    candidates["人"] = 0.8f
                    println("汉字识别调试: 符合'人'字条件")
                } else if (symmetry > 0.6f && convergence > 0.6f) {
                    candidates["入"] = 0.5f
                    println("汉字识别调试: 符合'入'字条件")
                }
            }
            3 -> {
                val hasHorizontal = features["hasHorizontalLine"] ?: 0f
                val symmetry = features["symmetry"] ?: 0f
                val convergence = features["convergencePoint"] ?: 0f
                val aspectRatio = features["aspectRatio"] ?: 1f
                val hasVertical = features["hasVerticalLine"] ?: 0f
                
                println("汉字识别调试: 三笔 - hasHorizontal=$hasHorizontal, symmetry=$symmetry, convergence=$convergence, aspectRatio=$aspectRatio")
                
                // 更严格的"大"字识别：需要明显的横线、高对称性、收敛性、合适的宽高比
                if (hasHorizontal > 0.7f && 
                    symmetry > 0.8f && 
                    convergence > 0.7f && 
                    aspectRatio > 0.9f && aspectRatio < 1.4f &&
                    hasVertical < 0.3f) { // "大"字不应该有明显的竖线
                    
                    candidates["大"] = 0.8f
                    println("汉字识别调试: 符合'大'字条件")
                } else if (hasHorizontal > 0.6f && symmetry > 0.6f) {
                    candidates["天"] = 0.4f
                    println("汉字识别调试: 符合'天'字条件")
                }
            }
        }
        
        println("汉字识别调试: 候选结果: $candidates")
        
        // 提高识别阈值，如果最高置信度低于0.6，则认为识别失败
        val bestMatch = candidates.maxByOrNull { it.value }
        val result = if (bestMatch != null && bestMatch.value >= 0.6f) {
            RecognitionResult(bestMatch.key, bestMatch.value, features)
        } else {
            RecognitionResult("", 0f, features)
        }
        
        println("汉字识别调试: 最终识别结果=${result.recognizedText}, 置信度=${result.confidence}")
        
        return result
    }
    
    /**
     * 提取几何特征
     */
    private fun extractGeometricFeatures(userStrokes: List<StrokeData>): Map<String, Float> {
        val features = mutableMapOf<String, Float>()
        
        println("特征提取调试: 分析用户笔迹，共${userStrokes.size}笔")
        
        if (userStrokes.isEmpty()) {
            println("特征提取调试: 用户笔迹为空")
            return features
        }
        
        // 计算边界框
        var minX = Float.MAX_VALUE
        var maxX = Float.MIN_VALUE
        var minY = Float.MAX_VALUE
        var maxY = Float.MIN_VALUE
        
        val allPoints = mutableListOf<Pair<Float, Float>>()
        
        for (stroke in userStrokes) {
            val vertices = stroke.vertices
            for (i in vertices.indices step 3) {
                val x = vertices[i]
                val y = vertices[i + 1]
                
                minX = minOf(minX, x)
                maxX = maxOf(maxX, x)
                minY = minOf(minY, y)
                maxY = maxOf(maxY, y)
                
                allPoints.add(Pair(x, y))
            }
        }
        
        val width = maxX - minX
        val height = maxY - minY
        
        // 宽高比
        features["aspectRatio"] = if (height > 0) width / height else 1f
        
        // 圆形度（周长²/面积的比值，圆形为4π）
        val perimeter = calculatePerimeter(userStrokes)
        val area = width * height
        features["circularity"] = if (area > 0) {
            (4 * PI * area / (perimeter * perimeter)).toFloat().coerceAtMost(1f)
        } else 0f
        
        // 检测直线特征
        features["hasHorizontalLine"] = detectHorizontalLines(userStrokes)
        features["hasVerticalLine"] = detectVerticalLines(userStrokes)
        
        // 主要角度
        features["dominantAngle"] = calculateDominantAngle(userStrokes)
        
        // 对称性
        features["symmetry"] = calculateSymmetry(allPoints, minX, maxX, minY, maxY)
        
        // 收敛点（多笔画是否汇聚）
        features["convergencePoint"] = calculateConvergence(userStrokes)
        
        println("特征提取调试: 提取的特征值:")
        features.forEach { (key, value) -> 
            println("  $key: $value")
        }
        
        return features
    }
    
    /**
     * 计算周长
     */
    private fun calculatePerimeter(userStrokes: List<StrokeData>): Float {
        var totalLength = 0f
        
        for (stroke in userStrokes) {
            val vertices = stroke.vertices
            for (i in 0 until vertices.size - 3 step 3) {
                val x1 = vertices[i]
                val y1 = vertices[i + 1]
                val x2 = vertices[i + 3]
                val y2 = vertices[i + 4]
                
                totalLength += sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
            }
        }
        
        return totalLength
    }
    
    /**
     * 检测水平线
     */
    private fun detectHorizontalLines(userStrokes: List<StrokeData>): Float {
        var horizontalScore = 0f
        
        for (stroke in userStrokes) {
            val vertices = stroke.vertices
            if (vertices.size >= 6) {
                val startX = vertices[0]
                val startY = vertices[1]
                val endX = vertices[vertices.size - 3]
                val endY = vertices[vertices.size - 2]
                
                val deltaX = abs(endX - startX)
                val deltaY = abs(endY - startY)
                
                if (deltaX > deltaY * 3) { // 水平线判定
                    horizontalScore = maxOf(horizontalScore, deltaX / (deltaX + deltaY))
                }
            }
        }
        
        return horizontalScore
    }
    
    /**
     * 检测垂直线
     */
    private fun detectVerticalLines(userStrokes: List<StrokeData>): Float {
        var verticalScore = 0f
        
        for (stroke in userStrokes) {
            val vertices = stroke.vertices
            if (vertices.size >= 6) {
                val startX = vertices[0]
                val startY = vertices[1]
                val endX = vertices[vertices.size - 3]
                val endY = vertices[vertices.size - 2]
                
                val deltaX = abs(endX - startX)
                val deltaY = abs(endY - startY)
                
                if (deltaY > deltaX * 3) { // 垂直线判定
                    verticalScore = maxOf(verticalScore, deltaY / (deltaX + deltaY))
                }
            }
        }
        
        return verticalScore
    }
    
    /**
     * 计算主要角度
     */
    private fun calculateDominantAngle(userStrokes: List<StrokeData>): Float {
        if (userStrokes.isEmpty()) return 0f
        
        val stroke = userStrokes[0] // 使用第一笔
        val vertices = stroke.vertices
        
        if (vertices.size >= 6) {
            val startX = vertices[0]
            val startY = vertices[1]
            val endX = vertices[vertices.size - 3]
            val endY = vertices[vertices.size - 2]
            
            return atan2(endY - startY, endX - startX) * 180f / PI.toFloat()
        }
        
        return 0f
    }
    
    /**
     * 计算对称性
     */
    private fun calculateSymmetry(
        points: List<Pair<Float, Float>>, 
        minX: Float, maxX: Float, 
        minY: Float, maxY: Float
    ): Float {
        if (points.size < 4) return 0f
        
        val centerX = (minX + maxX) / 2
        val centerY = (minY + maxY) / 2
        
        var symmetryScore = 0f
        var totalPoints = 0
        
        // 检查垂直对称性
        for (point in points) {
            val mirrorX = 2 * centerX - point.first
            val minDistance = points.minOfOrNull { other ->
                sqrt((other.first - mirrorX) * (other.first - mirrorX) + 
                     (other.second - point.second) * (other.second - point.second))
            } ?: Float.MAX_VALUE
            
            if (minDistance < 0.1f) { // 阈值
                symmetryScore += 1f
            }
            totalPoints++
        }
        
        return if (totalPoints > 0) symmetryScore / totalPoints else 0f
    }
    
    /**
     * 计算收敛性（多笔画汇聚程度）
     */
    private fun calculateConvergence(userStrokes: List<StrokeData>): Float {
        if (userStrokes.size < 2) return 0f
        
        val endpoints = mutableListOf<Pair<Float, Float>>()
        
        // 收集所有笔画的端点
        for (stroke in userStrokes) {
            val vertices = stroke.vertices
            if (vertices.size >= 6) {
                endpoints.add(Pair(vertices[0], vertices[1])) // 起点
                endpoints.add(Pair(vertices[vertices.size - 3], vertices[vertices.size - 2])) // 终点
            }
        }
        
        if (endpoints.size < 4) return 0f
        
        // 计算端点聚集程度
        var convergenceScore = 0f
        val threshold = 0.1f // 收敛阈值
        
        for (i in endpoints.indices) {
            var nearbyCount = 0
            for (j in endpoints.indices) {
                if (i != j) {
                    val distance = sqrt(
                        (endpoints[i].first - endpoints[j].first) * (endpoints[i].first - endpoints[j].first) +
                        (endpoints[i].second - endpoints[j].second) * (endpoints[i].second - endpoints[j].second)
                    )
                    if (distance < threshold) {
                        nearbyCount++
                    }
                }
            }
            convergenceScore = maxOf(convergenceScore, nearbyCount.toFloat() / (endpoints.size - 1))
        }
        
        return convergenceScore
    }
    
    /**
     * 计算识别准确度评分（改进版本）
     */
    private fun calculateRecognitionScore(result: RecognitionResult, targetCharacter: String): Float {
        println("识别评分调试: 识别结果='${result.recognizedText}', 目标字符='$targetCharacter', 置信度=${result.confidence}")
        
        val score = when {
            result.recognizedText == targetCharacter -> {
                // 完全匹配：使用置信度作为分数
                println("识别评分调试: 完全匹配")
                result.confidence
            }
            result.recognizedText.isNotEmpty() && isSimilarCharacter(result.recognizedText, targetCharacter) -> {
                // 相似字符：置信度 * 0.7
                println("识别评分调试: 相似字符匹配")
                result.confidence * 0.7f
            }
            result.recognizedText.isNotEmpty() -> {
                // 识别出了字符但不匹配：置信度 * 0.2（大幅降低分数）
                println("识别评分调试: 识别错误")
                result.confidence * 0.2f
            }
            else -> {
                // 识别失败：0分
                println("识别评分调试: 识别失败")
                0f
            }
        }
        
        println("识别评分调试: 最终识别评分=$score")
        return score
    }
    
    /**
     * 判断是否为相似字符
     */
    private fun isSimilarCharacter(recognized: String, target: String): Boolean {
        val similarGroups = listOf(
            listOf("0", "O", "o"),
            listOf("1", "I", "l"),
            listOf("2", "Z"),
            listOf("5", "S"),
            listOf("6", "G"),
            listOf("8", "B"),
            listOf("人", "入"),
            listOf("大", "天"),
            listOf("一", "丨")
        )
        
        return similarGroups.any { group ->
            group.contains(recognized) && group.contains(target)
        }
    }
    
    /**
     * 计算书写质量评分
     */
    private fun calculateWritingQuality(userStrokes: List<StrokeData>): Float {
        if (userStrokes.isEmpty()) return 0f
        
        var totalQuality = 0f
        
        for (stroke in userStrokes) {
            val vertices = stroke.vertices
            val widths = stroke.widths
            
            // 平滑度评分
            val smoothness = calculateSmoothness(vertices)
            
            // 长度适中性评分
            val lengthScore = calculateLengthScore(vertices)
            
            // 清晰度评分（基于线宽变化）
            val clarityScore = calculateClarityScore(widths)
            
            // 综合质量评分
            val strokeQuality = (smoothness * 0.4f + lengthScore * 0.3f + clarityScore * 0.3f)
            totalQuality += strokeQuality
        }
        
        return totalQuality / userStrokes.size
    }
    
    /**
     * 计算平滑度
     */
    private fun calculateSmoothness(vertices: List<Float>): Float {
        val verticesArray = vertices.toFloatArray()
        if (verticesArray.size < 9) return 1f // 点太少，认为是平滑的
        
        var totalCurvature = 0f
        var segmentCount = 0
        
        for (i in 0 until verticesArray.size - 6 step 3) {
            val x1 = verticesArray[i]
            val y1 = verticesArray[i + 1]
            val x2 = verticesArray[i + 3]
            val y2 = verticesArray[i + 4]
            val x3 = verticesArray[i + 6]
            val y3 = verticesArray[i + 7]
            
            // 计算曲率
            val curvature = calculateCurvature(x1, y1, x2, y2, x3, y3)
            totalCurvature += curvature
            segmentCount++
        }
        
        val avgCurvature = if (segmentCount > 0) totalCurvature / segmentCount else 0f
        return (1f - avgCurvature.coerceAtMost(1f)).coerceAtLeast(0f)
    }
    
    /**
     * 计算曲率
     */
    private fun calculateCurvature(x1: Float, y1: Float, x2: Float, y2: Float, x3: Float, y3: Float): Float {
        val a = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
        val b = sqrt((x3 - x2) * (x3 - x2) + (y3 - y2) * (y3 - y2))
        val c = sqrt((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1))
        
        if (a == 0f || b == 0f) return 0f
        
        val cosAngle = ((a * a + b * b - c * c) / (2 * a * b)).coerceIn(-1f, 1f)
        val angle = acos(cosAngle)
        
        return abs(PI.toFloat() - angle) / PI.toFloat() // 归一化曲率
    }
    
    /**
     * 计算长度评分
     */
    private fun calculateLengthScore(vertices: List<Float>): Float {
        val verticesArray = vertices.toFloatArray()
        var totalLength = 0f
        
        for (i in 0 until verticesArray.size - 3 step 3) {
            val x1 = verticesArray[i]
            val y1 = verticesArray[i + 1]
            val x2 = verticesArray[i + 3]
            val y2 = verticesArray[i + 4]
            
            totalLength += sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))
        }
        
        // 理想长度范围（归一化坐标系）
        val idealMinLength = 0.3f
        val idealMaxLength = 2.0f
        
        return when {
            totalLength < idealMinLength -> totalLength / idealMinLength
            totalLength > idealMaxLength -> idealMaxLength / totalLength
            else -> 1f
        }
    }
    
    /**
     * 计算清晰度评分
     */
    private fun calculateClarityScore(widths: List<Float>): Float {
        val widthsArray = widths.toFloatArray()
        if (widthsArray.size < 2) return 1f
        
        var totalVariation = 0f
        
        for (i in 1 until widthsArray.size) {
            totalVariation += abs(widthsArray[i] - widthsArray[i - 1])
        }
        
        val avgVariation = totalVariation / (widthsArray.size - 1)
        val normalizedVariation = avgVariation / 10f // 假设最大线宽为10
        
        return (1f - normalizedVariation.coerceAtMost(1f)).coerceAtLeast(0f)
    }
    
    /**
     * 生成识别反馈信息（改进版本）
     */
    private fun generateRecognitionFeedback(
        result: RecognitionResult,
        targetCharacter: String,
        recognitionScore: Float,
        qualityScore: Float,
        totalScore: Float
    ): String {
        val feedback = mutableListOf<String>()
        
        // 识别结果反馈
        when {
            result.recognizedText == targetCharacter -> {
                feedback.add("✓ 识别正确：${result.recognizedText}")
                if (result.confidence >= 0.9f) {
                    feedback.add("识别置信度很高")
                } else if (result.confidence >= 0.7f) {
                    feedback.add("识别置信度较高")
                } else {
                    feedback.add("识别置信度一般，建议写得更标准")
                }
            }
            result.recognizedText.isNotEmpty() -> {
                if (isSimilarCharacter(result.recognizedText, targetCharacter)) {
                    feedback.add("⚠ 识别为相似字符：${result.recognizedText}，目标：$targetCharacter")
                    feedback.add("字形相似但不完全正确")
                } else {
                    feedback.add("✗ 识别错误：识别为'${result.recognizedText}'，目标是'$targetCharacter'")
                    feedback.add("字形差异较大，请按照模板书写")
                }
            }
            else -> {
                feedback.add("✗ 无法识别字符")
                feedback.add("笔迹与目标字符'$targetCharacter'差异太大")
            }
        }
        
        // 总体评价
        when {
            totalScore >= 90f -> feedback.add("书写非常优秀")
            totalScore >= 80f -> feedback.add("书写很好")
            totalScore >= 70f -> feedback.add("书写良好")
            totalScore >= 60f -> feedback.add("书写一般")
            totalScore >= 30f -> feedback.add("书写需要改进")
            else -> feedback.add("书写需要大量练习")
        }
        
        // 具体建议
        if (result.recognizedText.isEmpty() || result.recognizedText != targetCharacter) {
            feedback.add("建议：仔细观察蓝色模板，按照正确的笔画顺序书写")
        }
        
        return feedback.joinToString("，")
    }
    
    /**
     * 生成位置偏差反馈信息
     */
    private fun generatePositionFeedback(overlapScore: Float, completenessScore: Float, totalScore: Float): String {
        val feedback = mutableListOf<String>()
        
        // 总体评价
        when {
            totalScore >= 90f -> feedback.add("书写非常优秀")
            totalScore >= 80f -> feedback.add("书写很好")
            totalScore >= 70f -> feedback.add("书写良好")
            totalScore >= 60f -> feedback.add("书写一般")
            totalScore >= 50f -> feedback.add("书写需要改进")
            else -> feedback.add("书写需要多练习")
        }
        
        // 重合度反馈
        when {
            overlapScore >= 0.8f -> feedback.add("笔迹位置很准确")
            overlapScore >= 0.6f -> feedback.add("笔迹位置基本准确")
            overlapScore >= 0.4f -> feedback.add("笔迹位置需要调整")
            else -> feedback.add("笔迹位置偏差较大")
        }
        
        // 完整度反馈
        when {
            completenessScore >= 0.9f -> feedback.add("字形很完整")
            completenessScore >= 0.7f -> feedback.add("字形比较完整")
            completenessScore >= 0.5f -> feedback.add("字形不够完整")
            else -> feedback.add("字形缺少部分笔画")
        }
        
        return feedback.joinToString("，")
    }
}